package schema

import (
	"geeorm/dialect"
	"go/ast"
	"reflect"
)

//Field包含3个成员变量，字段名Name，类型Type，和约束条件Tag
type Field struct {
	Name string
	Type string
	Tag string
}

//Schema主要包含被映射的对象Model，表名Name和字段Fields
//FieldNames包含所有的字段名（列名），fieldMap记录字段名和Field的映射关系，方便之后直接使用，无需遍历Fields
type Schema struct {
	Model interface{}
	Name string
	Fields []*Field
	FieldNames []string
	fieldMap map[string]*Field
}

func (schema *Schema) GetField(name string) *Field {
	return schema.fieldMap[name]
}

type ITableName interface {
	TableName() string
}

//将任意的对象解析为Schema实例
func Prase(dest interface{},d dialect.Dialect)*Schema{
	modelType:=reflect.Indirect(reflect.ValueOf(dest)).Type()
	var tableName string
	t, ok := dest.(ITableName)
	if !ok {
		tableName = modelType.Name()
	} else {
		tableName = t.TableName()
	}
	schema := &Schema{
		Model:    dest,
		Name:     tableName,
		fieldMap: make(map[string]*Field),
	}
	for i:=0;i<modelType.NumField();i++{
		p:=modelType.Field(i)
		if !p.Anonymous&&ast.IsExported(p.Name){
			field:=&Field{
				Name: p.Name,
				Type: d.DataTypeOf(reflect.Indirect(reflect.New(p.Type))),
			}
			if v,ok:=p.Tag.Lookup("geeorm");ok{
				field.Tag=v
			}
			schema.Fields=append(schema.Fields,field)
			schema.FieldNames=append(schema.FieldNames,p.Name)
			schema.fieldMap[p.Name]=field
		}
	}
	return schema
}

//将结构体转为（“TOM",18),("SAM",29)这样的格式
func (schema *Schema)RecordValues(dest interface{})[]interface{}{
	destValue:=reflect.Indirect(reflect.ValueOf(dest))
	var fieldValues []interface{}
	for _,field:=range schema.Fields{
		fieldValues=append(fieldValues,destValue.FieldByName(field.Name).Interface())
	}
	return fieldValues
}